# wirte by hasaki
# first edit on 2018/12/12
# last change on 2018/12/12
# 只管刷量的账号,只负责刷量
from math import pi,cos,sin

class ForTrade:
    def __init__(self):
        self.depth=None                              # 目标交易所的深度
        self.cash=None                               # 账户余额
        self.pos=None                                # 账户持仓

        self.target_exchange_symbol_ask1=None        # 目标交易所第一档深度
        self.target_exchange_symbol_bid1=None        # 目标交易所第一档深度

        self.busy_time=None                          # 频繁交易时段
        self.normal_time=None                        # 平常交易时段

        self.max_volume=None                            # 用户设置的最大成交量

        self.counter_for_curve=0                     # 用于刷量功能中曲线的参数
        self.curveList=[pi/8,pi/6,pi/4,pi/2,pi/10,pi,1,2,3]      # 用于驱动正弦余弦的参数

        self.orderDict={}                            # 下单字典

        self.slip=None                               # 交易滑点设置

    # -----------------------------------------------------------------------
    # 获取数据
    def dataIn(self,depth):
        '''目标交易所深度，值要买一卖一即可'''
        self.depth=depth
        self.target_exchange_symbol_ask1=depth['asks'][0]      # 目标交易所买一深度数据 [price,volume]
        self.target_exchange_symbol_bid1=depth['bids'][0]      # 目标交易所卖一深度数据
    
    def accountMsg(self,cash,pos):
        '''获取账户资产信息，包括现金和持仓'''
        self.cash=cash
        self.pos=pos
    
    def choseTime(self,busy_time,normal_time):
        '''择时成交'''
        self.busy_time=busy_time
        self.normal_time=normal_time
    
    def maxPos(self,max_volume):
        '''用户设置的最大成交量'''
        self.max_volume=max_volume
    
    def setting(self,slip):
        '''交易滑点'''
        self.slip=slip

    # -----------------------------------------------------------------------
    # 生成应该成交的价格
    def calculateTheMid(self):
        '''计算目标交易所买一卖一价的中间价'''
        return (self.target_exchange_symbol_ask1[0]+self.target_exchange_symbol_bid1[0])/2
    
    def sendWaveOrder(self,mode='sin'):
        '''在刷量区间内，使用一定波动率来回成交,正弦曲线的波动成交sin，余弦曲线的波动成交cos'''
        self.orderDict.clear()
        mid=self.calculateTheMid()
        d=self.target_exchange_symbol_ask1[0]-mid

        if self.counter_for_curve>=3:
            self.counter_for_curve=0
        else:
            self.counter_for_curve+=1

        factor=self.curveList[self.counter_for_curve]
        if mode=='sin':
            price=d*sin(factor)+mid
            self.sendOrder(price,self.max_volume)
        
        elif mode =='cos':
            price=d*cos(factor)+mid
            self.sendOrder(price,self.max_volume)
        
        elif mode=='mix':
            # 心型曲线
            price=d*(2*sin(factor)-sin(2*factor))
            self.sendOrder(price,self.max_volume)

        else:
            print("没有系统认识的波动曲线，若需要添加曲线，请到marketEngine.py的sendWaveOrder中添加")
            self.sendOrder(mid,self.max_volume)

    # ---------------------------------------------------------------------------------------------------
    # 发单
    def sendOrder(self,price,volume):
        '''买卖同时发单'''
        self.limitSell(price-self.slip,volume)
        self.limitBuy(price+self.slip,volume)

    def limitBuy(self,price,volume):
        '''发买单'''
        self.orderDict['limitBuy']=[price,volume]
    
    def limitSell(self,price,volume):
        '''发卖单'''
        self.orderDict['limitSell']=[price,volume]
    
    def run(self):
        '''启动刷量'''
        self.calculateTheMid()
        self.sendWaveOrder()
        return self.orderDict

class ForTrade2:
    def __init__(self):
        self.depth=None                              # 目标交易所的深度
        self.cash=None                               # 账户余额
        self.pos=None                                # 账户持仓

        self.target_exchange_symbol_ask1=None        # 目标交易所第一档深度
        self.target_exchange_symbol_bid1=None        # 目标交易所第一档深度

        self.busy_time=None                          # 频繁交易时段
        self.normal_time=None                        # 平常交易时段

        self.max_volume=None                            # 用户设置的最大成交量

        self.counter_for_curve=0                     # 用于刷量功能中曲线的参数
        self.curveList=[pi/8,pi/6,pi/4,pi/2,pi/3,-1,-2,-3,-4]    # 用于驱动正弦余弦的参数

        self.orderDict={}                            # 下单字典

        self.slip=None                               # 交易滑点设置

    # -----------------------------------------------------------------------
    # 获取数据
    def dataIn(self,depth):
        '''目标交易所深度，值要买一卖一即可'''
        self.depth=depth
        self.target_exchange_symbol_ask1=depth['asks'][0]      # 目标交易所买一深度数据 [price,volume]
        self.target_exchange_symbol_bid1=depth['bids'][0]      # 目标交易所卖一深度数据
    
    def accountMsg(self,cash,pos):
        '''获取账户资产信息，包括现金和持仓'''
        self.cash=cash
        self.pos=pos
    
    def choseTime(self,busy_time,normal_time):
        '''择时成交'''
        self.busy_time=busy_time
        self.normal_time=normal_time
    
    def maxPos(self,max_volume):
        '''用户设置的最大成交量'''
        self.max_volume=max_volume
    
    def setting(self,slip):
        '''交易滑点'''
        self.slip=slip

    # -----------------------------------------------------------------------
    # 生成应该成交的价格
    def calculateTheMid(self):
        '''计算目标交易所买一卖一价的中间价'''
        return (self.target_exchange_symbol_ask1[0]+self.target_exchange_symbol_bid1[0])/2

    # ---------------------------------------------------------------------------------------------------
    # 发单
    def sendOrder(self,price):
        '''买卖同时发单'''
        self.limitSell(price-self.slip,self.max_volume)
        self.limitBuy(price+self.slip,self.max_volume)
    
    def sendWaveOrder(self,mode='sin'):
        '''在刷量区间内，使用一定波动率来回成交,正弦曲线的波动成交sin，余弦曲线的波动成交cos'''
        self.orderDict.clear()
        mid=self.calculateTheMid()
        d=self.target_exchange_symbol_ask1[0]-mid

        if self.counter_for_curve>=8:
            self.counter_for_curve=0
        else:
            self.counter_for_curve+=1

        factor=self.curveList[self.counter_for_curve]
        if mode=='sin':
            price=d*sin(factor)+mid
            self.sendOrder(price)
        
        elif mode =='cos':
            price=d*cos(factor)+mid
            self.sendOrder(price)
        
        elif mode=='mix':
            # 心型曲线
            price=d*(2*sin(factor)-sin(2*factor))
            self.sendOrder(price)

        else:
            print("没有系统认识的波动曲线，若需要添加曲线，请到marketEngine.py的sendWaveOrder中添加")
            self.sendOrder(mid)

    def limitBuy(self,price,volume):
        '''发买单'''
        self.orderDict['limitBuy']=[price,volume]
    
    def limitSell(self,price,volume):
        '''发卖单'''
        self.orderDict['limitSell']=[price,volume]
    
    def run(self):
        '''启动刷量'''
        self.sendWaveOrder()
        return self.orderDict